using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FireStarter.Base;
using FireStarter.CodeGeneration;
using Firestarter.Test.Base;
using FireStarterModeller.BO;
using FireStarterModeller.Test;
using FireStarterModeller.Test.BO;
using Habanero.Base;
using Habanero.Base.Exceptions;
using Habanero.BO;
using Habanero.Util;
using NUnit.Framework;

namespace FireStarter.Test.CodeGeneration
{
    [TestFixture]
    public class TestMasterGenerator
    {
        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            TestUtilsDomain.SetupFixture();
        }

        [SetUp]
        public void Setup()
        {
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }

        [Test]
        public void Test_SetupGenerator_DMSolutionNull_ThrowsException()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = null;
            MasterGenerator masterGenerator = new MasterGenerator();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                masterGenerator.SetupGenerator(dmSolution);
                Assert.Fail("Should throw exception if dmSolution is null.");
            }
            //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("dmSolution", ex.Message);
            }
        }

        [Test]
        public void Test_Generate_DMSolutionNull_ThrowsException()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                masterGenerator.Generate();
                Assert.Fail("Should throw exception if dmSolution is null.");
            }
            //---------------Test Result -----------------------
            catch (PropertyMissingException ex)
            {
                StringAssert.Contains("DMSolution has not been set, probably because SetupGenerator has not been called first", ex.Message);
            }
        }

        [Test]
        public void Test_SetupGenerator_GenerationSettingsNull_ThrowsException()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();
            MasterGenerator masterGenerator = new MasterGenerator();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                masterGenerator.SetupGenerator(dmSolution);
                Assert.Fail("Should throw exception if generationSettings is null.");
            }
            //---------------Test Result -----------------------
            catch (PropertyMissingException ex)
            {
                StringAssert.Contains("Generation Settings cannot be null", ex.Message);
            }
        }

        [Test]
        public void Test_SetupGenerator_CodeTemplateLibraryNameNull_ThrowsException()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();
            dmSolution.GenerationSettings = new GenerationSettings();
            dmSolution.GenerationSettings.SolutionDirectory = TestUtilsShared.GetRandomString();
            dmSolution.GenerationSettings.SolutionName = "A" + TestUtilsShared.GetRandomString();
            dmSolution.GenerationSettings.CodeTemplateLibraryName = null;
            MasterGenerator masterGenerator = new MasterGenerator();
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.GenerationSettings.CodeTemplateLibraryName);
            //---------------Execute Test ----------------------
            try
            {
                masterGenerator.SetupGenerator(dmSolution);
                Assert.Fail("Should throw exception if CodeTemplateLibraryName is null.");
            }
            //---------------Test Result -----------------------
            catch (PropertyMissingException ex)
            {
                StringAssert.Contains("Code Template Library Name must be set.", ex.Message);
            }
        }

        [Test]
        public void Test_SetupGenerator_SolutionTypeNull_ThrowsException()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = new DMSolution();
            dmSolution.GenerationSettings = new GenerationSettings();
            dmSolution.GenerationSettings.SolutionDirectory = TestUtilsShared.GetRandomString();
            dmSolution.GenerationSettings.SolutionName = "A" +  TestUtilsShared.GetRandomString();
            dmSolution.GenerationSettings.SolutionType = null;
            MasterGenerator masterGenerator = new MasterGenerator();
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.GenerationSettings.SolutionType);
            //---------------Execute Test ----------------------
            try
            {
                masterGenerator.SetupGenerator(dmSolution);
                Assert.Fail("Should throw exception if SolutionType is null.");
            }
            //---------------Test Result -----------------------
            catch (PropertyMissingException ex)
            {
                StringAssert.Contains("Solution Type must be set.", ex.Message);
            }
        }

        [Test]
        public void Test_DMSolutionValidateFail_ShouldReturnResultUnsuccessful()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateInvalidDMSolution();
            dmSolution.SolutionName = "ff";
            dmSolution.GenerationSettings.SolutionType = new SolutionType();
            MasterGenerator masterGenerator = new MasterGenerator();
            masterGenerator.SetupGenerator(dmSolution);
            dmSolution.SolutionName = "";
            //---------------Assert Precondition----------------
            var boErrors = dmSolution.Validate();
            Assert.IsTrue(HasBOErrors(boErrors), "The Solution Should Have Errors");
            //---------------Execute Test ----------------------
            Result result = masterGenerator.Generate();
            //---------------Test Result -----------------------
            Assert.IsFalse(result.Successful);
            StringAssert.Contains("Validation of the domain model failed. Please" +
                Environment.NewLine + "correct the errors before generating code.", result.Message);
        }

        private static bool HasBOErrors(IList<IBOError> boErrors)
        {
            return boErrors.Count != 0 && new List<IBOError>(boErrors).Exists(t => t.Level == ErrorLevel.Error);
        }

        private static DMSolution CreateInvalidDMSolution()
        {
            DMSolution dmSolution = TestUtilsShared.CreateUnsavedValidDMSolution();
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedDefaultDMClass(dmSolution.DefaultAssembly);
            dmSolution.GenerationSettings = new GenerationSettings();
            dmSolution.GenerationSettings.SolutionName = "A" + TestUtilsCodeGen.GetRandomString();
            dmSolution.GenerationSettings.SolutionDirectory = Path.Combine(Directory.GetCurrentDirectory(), TestUtilsCodeGen.GetRandomString());
            dmSolution.GenerationSettings.CodeTemplateLibraryName = TestUtilsShared.GetRandomEnum<CodeTemplateEnum>();
            return dmSolution;
        }

        [Test]
        public void Test_SetsUpProjectGeneratorsForChosenProjectTypes()
        {
            //---------------Set up test pack-------------------
            ProjectType projectTypeUIBase = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_BASE);
            ProjectType projectTypeMainWin = CreateProjectType(GenerationTypes.PROJECT_TYPE_MAIN_WIN);
            ProjectType projectTypeUIVWG = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_VWG);

            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();

            string project1Name = CreateProjectTypeGeneration(dmSolution, projectTypeUIBase, true);
            string project2Name = CreateProjectTypeGeneration(dmSolution, projectTypeMainWin, true);
            string project3Name = CreateProjectTypeGeneration(dmSolution, projectTypeUIVWG, false);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmSolution.GenerationSettings);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(2, masterGenerator.ProjectGenerators.Count);
            AssertContainsProject(masterGenerator, typeof(UIBaseProjectGenerator), project1Name);
            AssertContainsProject(masterGenerator, typeof(WinProjectGenerator), project2Name);
        }

        [Test]
        public void Test_ProjectGenerator_ProjectName_ShouldCopyAcross()
        {
            //---------------Set up test pack-------------------
            ProjectType projectTypeUIBase = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_BASE);
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            string projectName = CreateProjectTypeGeneration(dmSolution, projectTypeUIBase, true);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(projectName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, masterGenerator.ProjectGenerators.Count);
            IProjectGenerator projectGenerator = masterGenerator.ProjectGenerators[0];
            Assert.AreEqual(projectName, projectGenerator.ProjectName);
        }

        [Test]
        public void Test_ProjectGenerator_ProjectPath_ShouldCopyAcross()
        {
            //---------------Set up test pack-------------------
            ProjectType projectTypeUIBase = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_BASE);
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            string solutionPath = Path.Combine(Directory.GetCurrentDirectory(), TestUtilsCodeGen.GetRandomString());
            dmSolution.GenerationSettings.SolutionDirectory = solutionPath;
            string projectName = CreateProjectTypeGeneration(dmSolution, projectTypeUIBase, true);
            string projectPath = solutionPath + Path.DirectorySeparatorChar + projectName;
            //---------------Assert Precondition----------------
            Assert.IsNotNull(solutionPath);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, masterGenerator.ProjectGenerators.Count);
            IProjectGenerator projectGenerator = masterGenerator.ProjectGenerators[0];
            Assert.AreEqual(projectPath, projectGenerator.ProjectPath);
        }

        [Test]
        public void Test_SetupGenerator_SolutionDirectory_WhenSlnPathIsRooted_ShouldCopyAcross()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            string solutionDirectory = TestUtilsCodeGen.GetRootedPath("codeFolder");
            dmSolution.GenerationSettings.SolutionDirectory = solutionDirectory;
            //---------------Assert Precondition----------------
            Assert.IsNotNull(solutionDirectory);
            Assert.IsTrue(Path.IsPathRooted(solutionDirectory));
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            ISolutionGenerator solutionGenerator = masterGenerator.SolutionGenerator;
            Assert.IsNotNull(solutionGenerator);
            Assert.AreEqual(solutionDirectory, solutionGenerator.SolutionDirectory);
        }

        [Test]
        public void Test_SetupGenerator_SolutionDirectory_WhenBothPathsRooted_ShouldUseSlnPath()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            const string solutionDirectory = @"C:\myProject\codeFolder";
            dmSolution.GenerationSettings.SolutionDirectory = solutionDirectory;
            const string fstartDirectory = @"C:\myProject\fstartFolder";
            dmSolution.SolutionDirectory = fstartDirectory;
            //---------------Assert Precondition----------------
            Assert.IsTrue(Path.IsPathRooted(solutionDirectory));
            Assert.IsTrue(Path.IsPathRooted(fstartDirectory));
            Assert.AreNotEqual(solutionDirectory, fstartDirectory);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionDirectory, masterGenerator.SolutionGenerator.SolutionDirectory);
        }

        [Test]
        public void Test_SetupGenerator_SolutionDirectory_WhenSlnPathRelative_AndFStartPathRooted_ShouldCombinePaths()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            const string solutionDirectory = @"codeFolder";
            dmSolution.GenerationSettings.SolutionDirectory = solutionDirectory;
            const string fstartDirectory = @"C:\fstartFolder";
            dmSolution.SolutionDirectory = fstartDirectory;
            //---------------Assert Precondition----------------
            Assert.IsFalse(Path.IsPathRooted(solutionDirectory));
            Assert.IsTrue(Path.IsPathRooted(fstartDirectory));
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            string expectedPath = Path.Combine(fstartDirectory, solutionDirectory);
            Assert.AreEqual(expectedPath, masterGenerator.SolutionGenerator.SolutionDirectory);
        }

        [Test]
        public void Test_SetupGenerator_SolutionDirectory_WhenSlnPathIsNull_AndFStartPathRooted_ShouldUseFStartPath()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.GenerationSettings.SolutionDirectory = null;
            const string fstartDirectory = @"C:\FstartFolder";
            dmSolution.SolutionDirectory = fstartDirectory;
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.GenerationSettings.SolutionDirectory);
            Assert.IsTrue(Path.IsPathRooted(fstartDirectory));
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(fstartDirectory, masterGenerator.SolutionGenerator.SolutionDirectory);
        }

        [Test]
        public void Test_SetupGenerator_SolutionDirectory_WhenNeitherPathRooted_ShouldThrowException()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.GenerationSettings.SolutionDirectory = "codeFolder";
            dmSolution.SolutionDirectory = @"RelativeMyProject\FstartFolder";
            //---------------Assert Precondition----------------
            Assert.IsFalse(Path.IsPathRooted(dmSolution.GenerationSettings.SolutionDirectory));
            Assert.IsFalse(Path.IsPathRooted(dmSolution.SolutionDirectory));
            //---------------Execute Test ----------------------
            var exception = Assert.Throws<Exception>(() =>
            {
                masterGenerator.SetupGenerator(dmSolution);
            });
            //---------------Test Result -----------------------
            StringAssert.Contains("Please specify a rooted solution directory.", exception.Message);
        }

        [Test]
        public void Test_SetupGenerator_CopiesToSolutionGenerator_HabaneroPath()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.GenerationSettings.HabaneroDllPath =  TestUtilsCodeGen.GetRootedPath(TestUtilsShared.GetRandomString());
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmSolution.GenerationSettings);
            string habaneroDllPath = dmSolution.GenerationSettings.HabaneroDllPath;
            Assert.IsNotNull(habaneroDllPath);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(habaneroDllPath, masterGenerator.SolutionGenerator.HabaneroReferencePath);
        }

        [Test]
        public void Test_SetupGenerator_HabaneroReferencePath_WhenLibPathIsRooted_ShouldCopyAcross()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            string libPath = TestUtilsCodeGen.GetRootedPath("libFolder");
            dmSolution.GenerationSettings.HabaneroDllPath = libPath;
            //---------------Assert Precondition----------------
            Assert.IsNotNull(libPath);
            Assert.IsTrue(Path.IsPathRooted(libPath));
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            ISolutionGenerator solutionGenerator = masterGenerator.SolutionGenerator;
            Assert.IsNotNull(solutionGenerator);
            Assert.AreEqual(libPath, solutionGenerator.HabaneroReferencePath);
        }

        [Test]
        public void Test_SetupGenerator_HabaneroReferencePath_WhenBothPathsRooted_ShouldUseLibPath()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            const string libPath = @"C:\myProject\LibFolder";
            dmSolution.GenerationSettings.HabaneroDllPath = libPath;
            const string fstartDirectory = @"C:\myProject\fstartFolder";
            dmSolution.SolutionDirectory = fstartDirectory;
            //---------------Assert Precondition----------------
            Assert.IsTrue(Path.IsPathRooted(libPath));
            Assert.IsTrue(Path.IsPathRooted(fstartDirectory));
            Assert.AreNotEqual(libPath, fstartDirectory);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(libPath, masterGenerator.SolutionGenerator.HabaneroReferencePath);
        }

        [Test]
        public void Test_SetupGenerator_HabaneroReferencePath_WhenLibPathRelative_AndFStartPathRooted_ShouldCombinePaths()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            const string libPath = @"libFolder";
            dmSolution.GenerationSettings.HabaneroDllPath = libPath;
            const string fstartDirectory = @"C:\fstartFolder";
            dmSolution.SolutionDirectory = fstartDirectory;
            //---------------Assert Precondition----------------
            Assert.IsFalse(Path.IsPathRooted(libPath));
            Assert.IsTrue(Path.IsPathRooted(fstartDirectory));
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            string expectedPath = Path.Combine(fstartDirectory, libPath);
            Assert.AreEqual(expectedPath, masterGenerator.SolutionGenerator.HabaneroReferencePath);
        }

        [Test]
        public void Test_SetupGenerator_HabaneroReferencePath_WhenLibPathIsNull_AndFStartPathRooted_ShouldUseFStartPath()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.GenerationSettings.HabaneroDllPath = null;
            const string fstartDirectory = @"C:\fstartFolder";
            dmSolution.SolutionDirectory = fstartDirectory;
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.GenerationSettings.HabaneroDllPath);
            Assert.IsTrue(Path.IsPathRooted(fstartDirectory));
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(fstartDirectory, masterGenerator.SolutionGenerator.HabaneroReferencePath);
        }

        [Test]
        public void Test_SetupGenerator_HabaneroReferencePath_WhenNeitherPathRooted_ShouldThrowException()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.GenerationSettings.HabaneroDllPath = "libFolder";
            dmSolution.SolutionDirectory = @"RelativeMyProject\fstartFolder";
            //---------------Assert Precondition----------------
            Assert.IsFalse(Path.IsPathRooted(dmSolution.GenerationSettings.HabaneroDllPath));
            Assert.IsFalse(Path.IsPathRooted(dmSolution.SolutionDirectory));
            //---------------Execute Test ----------------------
            var exception = Assert.Throws<Exception>(() =>
            {
                masterGenerator.SetupGenerator(dmSolution);
            });
            //---------------Test Result -----------------------
            StringAssert.Contains("Please specify a rooted solution directory.", exception.Message);
        }
        
        [Test]
        public void Test_SetupGenerator_SolutionName_ShouldCopyAcross()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateDMSolution();
            dmSolution.GenerationSettings.SolutionDirectory =Path.Combine(Directory.GetCurrentDirectory(), TestUtilsCodeGen.GetRandomString());
            dmSolution.GenerationSettings.SolutionName = "A" + TestUtilsCodeGen.GetRandomString();
            dmSolution.GenerationSettings.CodeTemplateLibraryName = TestUtilsShared.GetRandomEnum<CodeTemplateEnum>();
            string solutionName = dmSolution.GenerationSettings.SolutionName;
            //---------------Assert Precondition----------------
            Assert.IsNotNull(solutionName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            ISolutionGenerator solutionGenerator = masterGenerator.SolutionGenerator;
            Assert.IsNotNull(solutionGenerator);
            Assert.AreEqual(solutionName, solutionGenerator.SolutionName);
        }

        [Test]
        public void Test_SetupGenerator_SolutionName_NotSet_ShouldThrowException()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateDMSolution();
            dmSolution.GenerationSettings.SolutionDirectory = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.GenerationSettings.SolutionName);
            //---------------Execute Test ----------------------
            try
            {
                masterGenerator.SetupGenerator(dmSolution);
                Assert.Fail("Should fail when solution name is not set.");
            }
            //---------------Test Result -----------------------
            catch (PropertyMissingException ex)
            {
                StringAssert.Contains("Solution name must be set.", ex.Message);
            }
        }

        [Test]
        public void Test_SetupGenerator_CopiesBOProjectNameOntoDMSolution()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.BOProjectName = "";
            ProjectType boProjectType = CreateProjectType(GenerationTypes.PROJECT_TYPE_BO);
            string boProjectName = CreateProjectTypeGeneration(dmSolution, boProjectType, true);
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.BOProjectName);
            Assert.IsNotNull(boProjectName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(boProjectName, dmSolution.BOProjectName);
        }

        [Test]
        public void Test_SetupGenerator_CopiesBOProjectNameOntoDMSolution_NullIfNoBOProject()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.BOProjectName = "";
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.BOProjectName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.IsNull(dmSolution.BOProjectName);
        }

        [Test]
        public void Test_SetupGenerator_CopiesLogicProjectNameOntoDMSolution()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.LogicProjectName = "";

            ProjectType projectType = CreateProjectType(GenerationTypes.PROJECT_TYPE_LOGIC);
            string projectName = CreateProjectTypeGeneration(dmSolution, projectType, true);
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.LogicProjectName);
            Assert.IsNotNull(projectName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(projectName, dmSolution.LogicProjectName);
        }

        [Test]
        public void Test_SetupGenerator_CopiesUIProjectNameOntoDMSolution()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.BOProjectName = "";

            ProjectType projectType = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_BASE);
            string projectName = CreateProjectTypeGeneration(dmSolution, projectType, true);
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.BOProjectName);
            Assert.IsNotNull(projectName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(projectName, dmSolution.UIProjectName);
        }

        [Test]
        public void Test_SetupGenerator_CopiesUIVWGProjectNameOntoDMSolution()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.BOProjectName = "";

            ProjectType projectType = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_VWG);
            string projectName = CreateProjectTypeGeneration(dmSolution, projectType, true);
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.BOProjectName);
            Assert.IsNotNull(projectName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(projectName, dmSolution.UIVWGProjectName);
        }

        [Test]
        public void Test_SetupGenerator_CopiesUIWinProjectNameOntoDMSolution()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.BOProjectName = "";

            ProjectType projectType = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_WIN);
            string projectName = CreateProjectTypeGeneration(dmSolution, projectType, true);
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.BOProjectName);
            Assert.IsNotNull(projectName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(projectName, dmSolution.UIWinProjectName);
        }

        [Test]
        public void Test_SetupGenerator_CopiesBOTestProjectNameOntoDMSolution()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.BOProjectName = "";

            ProjectType projectType = CreateProjectType(GenerationTypes.PROJECT_TYPE_TEST_BO);
            string projectName = CreateProjectTypeGeneration(dmSolution, projectType, true);
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.BOProjectName);
            Assert.IsNotNull(projectName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(projectName, dmSolution.BOTestProjectName);
        }

        [Test]
        public void Test_SetupGenerator_CopiesApplicationNameOntoDMSolution()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.BOProjectName = "";
            ProjectType projectType = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_WIN);
            string projectName = CreateProjectTypeGeneration(dmSolution, projectType, true);
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.BOProjectName);
            Assert.IsNotNull(projectName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(projectName, dmSolution.UIWinProjectName);
        }

        [Test]
        public void Test_Generate_SolutionIsGenerated()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.GenerationSettings.SolutionDirectory = Path.Combine(Directory.GetCurrentDirectory(), TestUtilsCodeGen.GetRandomString());
            dmSolution.GenerationSettings.SolutionName = "A" + TestUtilsCodeGen.GetRandomString();
            dmSolution.GenerationSettings.CodeTemplateLibraryName = TestUtilsShared.GetRandomEnum<CodeTemplateEnum>();
            masterGenerator.SetupGenerator(dmSolution);
            SolutionGeneratorStub solutionGeneratorStub = new SolutionGeneratorStub();
            masterGenerator.SolutionGenerator = solutionGeneratorStub;
            //---------------Assert Precondition----------------
            var boErrors = dmSolution.Validate();
            Assert.AreEqual(0, boErrors.Count, "Should be no Errors But : " + GetErrors(boErrors));
            Assert.IsFalse(solutionGeneratorStub.HasGenerated);
            //---------------Execute Test ----------------------
            Result result = masterGenerator.Generate();
            //---------------Test Result -----------------------
            Assert.IsTrue(solutionGeneratorStub.HasGenerated);
            Assert.IsTrue(result.Successful);
        }

        [Test]
        public void Test_Generate_UsesCodeTemplateLibraryFromGenerationSettings()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.GenerationSettings.SolutionDirectory = Path.Combine(Directory.GetCurrentDirectory(), TestUtilsCodeGen.GetRandomString());
         //   dmSolution.GenerationSettings.SolutionName = TestUtilsCodeGen.GetRandomString();
            CodeTemplateEnum codeTemplateLibrary = TestUtilsShared.GetRandomEnum<CodeTemplateEnum>();
            dmSolution.GenerationSettings.CodeTemplateLibraryName = codeTemplateLibrary;
            masterGenerator.SetupGenerator(dmSolution);
            SolutionGeneratorStub solutionGeneratorStub = new SolutionGeneratorStub();
            masterGenerator.SolutionGenerator = solutionGeneratorStub;
            //---------------Assert Precondition----------------
            var boErrors = dmSolution.Validate();
            Assert.AreEqual(0, boErrors.Count, "Should be no Errors But : " + GetErrors(boErrors));
            Assert.IsFalse(solutionGeneratorStub.HasGenerated);
            //---------------Execute Test ----------------------
            Result result = masterGenerator.Generate();
            //---------------Test Result -----------------------
            Assert.IsTrue(solutionGeneratorStub.HasGenerated);
            Assert.IsTrue(result.Successful);
            Assert.AreEqual(codeTemplateLibrary, solutionGeneratorStub.CodeTemplateLibrary);
        }
        private string GetErrors(IEnumerable<IBOError> errors)
        {
            return errors.Aggregate("", AppendMessage);
        }

        private string AppendMessage(string current, IBOError boError)
        {
            return StringUtilities.AppendMessage(current, boError.Message);
        }

        [Test]
        public void Test_SetupGenerator_ProjectGeneratorsAddedToSolutionGenerator()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            ProjectType projectTypeUIVWG = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_VWG);
            ProjectType projectTypeUIWin = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_WIN);
            CreateProjectTypeGeneration(dmSolution, projectTypeUIVWG, true);
            CreateProjectTypeGeneration(dmSolution, projectTypeUIWin, true);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(2, masterGenerator.SolutionGenerator.ProjectGenerators.Count);
            IProjectGenerator projectGeneratorUIWin = GetProjectGenerator(masterGenerator.ProjectGenerators,
                                                                          typeof(UIWinProjectGenerator));
            IProjectGenerator projectGeneratorUIVWG = GetProjectGenerator(masterGenerator.ProjectGenerators,
                                                                          typeof(UIVWGProjectGenerator));
            Assert.Contains(projectGeneratorUIWin, masterGenerator.SolutionGenerator.ProjectGenerators);
            Assert.Contains(projectGeneratorUIVWG, masterGenerator.SolutionGenerator.ProjectGenerators);
        }

        [Test]
        public void Test_SetupGenerator_ProjectGeneratorsAddedToSolutionGenerator_IncorrectHierarchy()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            ProjectType projectTypeMainVWG = CreateProjectType(GenerationTypes.PROJECT_TYPE_MAIN_VWG);
            ProjectType projectTypeUIVWG = CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_VWG);
            CreateProjectTypeGeneration(dmSolution, projectTypeMainVWG, true);
            CreateProjectTypeGeneration(dmSolution, projectTypeUIVWG, true);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(2, masterGenerator.SolutionGenerator.ProjectGenerators.Count);
            IProjectGenerator projectGenerator1 = masterGenerator.ProjectGenerators[0];
            IProjectGenerator projectGenerator2 = masterGenerator.ProjectGenerators[1];
            StringAssert.Contains(projectTypeUIVWG.Name, projectGenerator1.ProjectFileName);
            StringAssert.Contains(projectTypeMainVWG.Name, projectGenerator2.ProjectFileName);
            Assert.AreEqual(projectGenerator1, masterGenerator.SolutionGenerator.ProjectGenerators[0]);
            Assert.AreEqual(projectGenerator2, masterGenerator.SolutionGenerator.ProjectGenerators[1]);
        }

        [Test]
        public void Test_SetupGenerator_CopiesSolutionGeneratorOntoProjectGenerator()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            ProjectType projectTypeMainVWG = CreateProjectType(GenerationTypes.PROJECT_TYPE_MAIN_VWG);
            CreateProjectTypeGeneration(dmSolution, projectTypeMainVWG, true);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, masterGenerator.SolutionGenerator.ProjectGenerators.Count);
            IProjectGenerator projectGenerator = masterGenerator.ProjectGenerators[0];
            Assert.AreEqual(projectGenerator, masterGenerator.SolutionGenerator.ProjectGenerators[0]);
            Assert.AreEqual(masterGenerator.SolutionGenerator, projectGenerator.SolutionGenerator);
        }

        [Test]
        public void Test_SetupGenerator_CopiesToSolutionGenerator_SolutionTypeName()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmSolution.GenerationSettings);
            Assert.IsNotNull(dmSolution.GenerationSettings.SolutionType);
            string solutionTypeName = dmSolution.GenerationSettings.SolutionType.Name;
            Assert.IsNotNull(solutionTypeName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionTypeName, masterGenerator.SolutionGenerator.SolutionTypeName);
        }

        [Test]
        public void Test_SetupGenerator_CopiesToSolutionGenerator_DMSolution()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmSolution);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(dmSolution, masterGenerator.SolutionGenerator.ModelSolution);
        }

        [Test]
        public void Test_SetupGenerator_CopiesToSolutionGenerator_ModelClasses()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.DefaultAssembly = dmSolution.Assemblies.CreateBusinessObject();
            dmSolution.DefaultAssembly.Classes.CreateBusinessObject();
            IList<IModelClass> modelClasses = ((IModelSolution)dmSolution).ModelClasses;
            //---------------Assert Precondition----------------
            Assert.IsNotNull(modelClasses);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(modelClasses, masterGenerator.SolutionGenerator.ModelClasses);
        }

        [Test]
        public void Test_SetupGenerator_CopiesToSolutionGenerator_ClassDefs()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            masterGenerator.ClassDefsXml = TestUtilsCodeGen.GetRandomString();
            DMSolution dmSolution = CreateValidDMSolution();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(masterGenerator.ClassDefsXml);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(masterGenerator.ClassDefsXml, masterGenerator.SolutionGenerator.ClassDefsString);
        }

        [Test]
        public void Test_SetupGenerator_CopiesToSolutionGenerator_CodeTemplate()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            CodeTemplateEnum codeTemplate = TestUtilsShared.GetRandomEnum<CodeTemplateEnum>();
            DMSolution dmSolution = CreateValidDMSolution();
            dmSolution.GenerationSettings.CodeTemplateLibraryName = codeTemplate;
            //---------------Assert Precondition----------------
            Assert.IsNotNull(codeTemplate);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(codeTemplate, masterGenerator.SolutionGenerator.CodeTemplate);
        }

        [Test]
        public void Test_SetupGenerator_CopiesToSolutionGenerator_ApplicationName()
        {
            //---------------Set up test pack-------------------
            MasterGenerator masterGenerator = new MasterGenerator();
            DMSolution dmSolution = CreateValidDMSolution();
            string solutionName = "A" + TestUtilsCodeGen.GetRandomString();
            dmSolution.GenerationSettings.SolutionName = solutionName;

            //---------------Assert Precondition----------------
            Assert.IsNotNull(solutionName);
            //---------------Execute Test ----------------------
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName, masterGenerator.SolutionGenerator.ModelSolution.ApplicationName);
        }

        private static IProjectGenerator GetProjectGenerator(List<IProjectGenerator> projectGenerators, Type type)
        {
            foreach (IProjectGenerator projectGenerator in projectGenerators)
            {
                if (projectGenerator.GetType() == type) return projectGenerator;
            }
            return null;
        }

        private static string CreateProjectTypeGeneration(DMSolution dmSolution,
            ProjectType projectType, bool toBeGenerated)
        {
            ProjectTypeGeneration projectTypeGeneration = dmSolution.GenerationSettings.ProjectTypeGenerations.CreateBusinessObject();
            projectTypeGeneration.ProjectType = projectType;
            string projectName = TestUtilsCodeGen.GetRandomString() + "." + projectType.Name;
            projectTypeGeneration.ProjectName = projectName;
            projectTypeGeneration.ToBeGenerated = toBeGenerated;
            return projectName;
        }

        private static void AssertContainsProject(MasterGenerator masterGenerator, Type type, string projectName)
        {
            foreach (IProjectGenerator projectGenerator in masterGenerator.ProjectGenerators)
            {
                if (projectGenerator.GetType() == type)
                {
                    Assert.AreEqual(projectName, projectGenerator.ProjectName);
                    return;
                }
            }
            Assert.Fail(type + " not found in default ProjectGenerators");
        }

        [Test]
        public void Test_GetProjectGenerator_ReturnsCorrectTypes()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsDMSolution.CreateUnsavedValidDMSolution();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            //---------------Test Result -----------------------
            Assert.IsInstanceOf(typeof(BoProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_BO, dmSolution));
            Assert.IsInstanceOf(typeof(LogicProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_LOGIC, dmSolution));
            Assert.IsInstanceOf(typeof(UIBaseProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_UI_BASE, dmSolution));
            Assert.IsInstanceOf(typeof(UIVWGProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_UI_VWG, dmSolution));
            Assert.IsInstanceOf(typeof(UIWinProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_UI_WIN, dmSolution));
            Assert.IsInstanceOf(typeof(VWGProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_MAIN_VWG, dmSolution));
            Assert.IsInstanceOf(typeof(WinProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_MAIN_WIN, dmSolution));
            Assert.IsInstanceOf(typeof(BOTestProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_TEST_BO, dmSolution));
            Assert.IsInstanceOf(typeof(BaseTestProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_TEST_BASE, dmSolution));
            Assert.IsInstanceOf(typeof(FireStarter.CodeGeneration.LogicTestProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_TEST_LOGIC, dmSolution));
            Assert.IsInstanceOf(typeof(UITestProjectGenerator), MasterGenerator.GetProjectGenerator(GenerationTypes.PROJECT_TYPE_TEST_UI, dmSolution));
        }

        //[Test]
        //public void Test_GetProjectGenerator_ReturnsCorrectTypes_WinSolutionType()
        //{
        //    //---------------Set up test pack-------------------
        //    DMSolution dmSolution = CreateValidDMSolution();
        //    SolutionType solutionType = CreateSolutionType(GenerationTypes.SOLUTION_TYPE_WIN);
        //    dmSolution.GenerationSettings.SolutionType = solutionType;

        //    //---------------Assert Precondition----------------
        //    Assert.AreEqual(GenerationTypes.SOLUTION_TYPE_WIN,
        //                    dmSolution.GenerationSettings.SolutionType.Name);
        //    //---------------Execute Test ----------------------
        //    IProjectGenerator projectGenerator = MasterGenerator.GetProjectGenerator(
        //        GenerationTypes.PROJECT_TYPE_UI, dmSolution);
        //    //---------------Test Result -----------------------
        //    Assert.IsInstanceOf(typeof(UIWinProjectGenerator), projectGenerator);
        //}

        [Test]
        public void Test_GetProjectGenerator_UnknownProjectType_ThrowsException()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            try
            {
                MasterGenerator.GetProjectGenerator(TestUtilsCodeGen.GetRandomString(), CreateDMSolution());
                Assert.Fail("Should throw exception");
            }
            //---------------Test Result -----------------------
            catch (HabaneroDeveloperException ex)
            {
                StringAssert.Contains("Code generation does not yet support the project type:", ex.Message);
            }
        }

        [Test]
        public void Test_Generate_AllProjectsAreGenerated()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateValidDMSolution();
            MasterGenerator masterGenerator = new MasterGenerator();
            masterGenerator.SetupGenerator(dmSolution);
            ProjectGeneratorStub projectGenerator1 = new ProjectGeneratorStub();
            ProjectGeneratorStub projectGenerator2 = new ProjectGeneratorStub();
            masterGenerator.ProjectGenerators = new List<IProjectGenerator>();
            masterGenerator.ProjectGenerators.Add(projectGenerator1);
            masterGenerator.ProjectGenerators.Add(projectGenerator2);
            //---------------Assert Precondition----------------
            var boErrors = dmSolution.Validate();
            Assert.AreEqual(0, boErrors.Count, "Should be no Errors But : " + GetErrors(boErrors));
            Assert.IsFalse(projectGenerator1.HasGenerated);
            Assert.IsFalse(projectGenerator2.HasGenerated);
            //---------------Execute Test ----------------------
            Result result = masterGenerator.Generate();
            //---------------Test Result -----------------------
            Assert.IsTrue(projectGenerator1.HasGenerated);
            Assert.IsTrue(projectGenerator2.HasGenerated);
            Assert.IsTrue(result.Successful);
            //---------------Tear Down--------------------------
            Directory.Delete(masterGenerator.SolutionGenerator.SolutionDirectory, true);
        }

        private string GetMessage(IList<IBOError> boErrors)
        {
            string message = "";
            foreach (var boError in boErrors)
            {
                message = StringUtilities.AppendMessage(message, boError.Message);
            }
            return message;
        }

        [Test]
        public void Test_Generate_ShouldSetNeedsRegenerationToFalseAfterGenerating()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            DMClass dmClass1 = TestUtilsShared.CreateSavedDMClass(dmSolution.DefaultAssembly);
            DMClass dmClass2 = TestUtilsShared.CreateSavedDMClass(dmSolution.DefaultAssembly);
            UpdateSolutionWithValidDetailsForGeneration(dmSolution);
            MasterGenerator masterGenerator = new MasterGenerator();
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Assert Precondition----------------
            Assert.IsTrue(dmClass1.GenerateCode);
            Assert.IsTrue(dmClass1.NeedsRegeneration);
            Assert.IsTrue(dmClass2.GenerateCode);
            Assert.IsTrue(dmClass2.NeedsRegeneration);
            //---------------Execute Test ----------------------
            Result result = masterGenerator.Generate();
            //---------------Test Result -----------------------
            Assert.AreEqual(null, result.Message);
            Assert.IsTrue(result.Successful);
            Assert.IsTrue(dmClass1.GenerateCode);
            Assert.IsFalse(dmClass1.NeedsRegeneration);
            Assert.IsTrue(dmClass2.GenerateCode);
            Assert.IsFalse(dmClass2.NeedsRegeneration);
            //---------------Tear Down--------------------------
            Directory.Delete(masterGenerator.SolutionGenerator.SolutionDirectory, true);
        }

        [Test]
        public void Test_Generate_WhenDMClassGenerateCodeIsFalse_ShouldNotSetNeedsRegenerationToFalseAfterGenerating()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsShared.CreateSavedDMSolution();
            DMClass dmClass1 = TestUtilsShared.CreateSavedDMClass(dmSolution.DefaultAssembly);
            DMClass dmClass2 = TestUtilsShared.CreateSavedDMClass(dmSolution.DefaultAssembly);
            dmClass2.GenerateCode = false;
            UpdateSolutionWithValidDetailsForGeneration(dmSolution);
            MasterGenerator masterGenerator = new MasterGenerator();
            masterGenerator.SetupGenerator(dmSolution);
            //---------------Assert Precondition----------------
            Assert.IsTrue(dmClass1.GenerateCode);
            Assert.IsTrue(dmClass1.NeedsRegeneration);
            Assert.IsFalse(dmClass2.GenerateCode);
            Assert.IsTrue(dmClass2.NeedsRegeneration);
            //---------------Execute Test ----------------------
            Result result = masterGenerator.Generate();
            //---------------Test Result -----------------------
            Assert.AreEqual(null, result.Message);
            Assert.IsTrue(result.Successful);
            Assert.IsTrue(dmClass1.GenerateCode);
            Assert.IsFalse(dmClass1.NeedsRegeneration);
            Assert.IsFalse(dmClass2.GenerateCode);
            Assert.IsTrue(dmClass2.NeedsRegeneration);
            //---------------Tear Down--------------------------
            Directory.Delete(masterGenerator.SolutionGenerator.SolutionDirectory, true);
        }

        [Test]
        public void Test_GetSuitableProjectName_Simple_ForMainWin()
        {
            //---------------Set up test pack-------------------
            string solutionName = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string projectName = MasterGenerator.GetSuitableProjectName(
                solutionName,
                GenerationTypes.PROJECT_TYPE_MAIN_WIN,
                GenerationTypes.SOLUTION_TYPE_WIN);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName, projectName);
        }

        [Test]
        public void Test_GetSuitableProjectName_Simple_ForMainVWG()
        {
            //---------------Set up test pack-------------------
            string solutionName = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string projectName = MasterGenerator.GetSuitableProjectName(
                solutionName,
                GenerationTypes.PROJECT_TYPE_MAIN_VWG,
                GenerationTypes.SOLUTION_TYPE_VWG);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName, projectName);
        }

        [Test]
        public void Test_GetSuitableProjectName_Dual_ForMainWin()
        {
            //---------------Set up test pack-------------------
            string solutionName = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string projectName = MasterGenerator.GetSuitableProjectName(
                solutionName,
                GenerationTypes.PROJECT_TYPE_MAIN_WIN,
                GenerationTypes.SOLUTION_TYPE_DUALWINVWG);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName + ".Win", projectName);
        }

        [Test]
        public void Test_GetSuitableProjectName_Dual_ForMainVWG()
        {
            //---------------Set up test pack-------------------
            string solutionName = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string projectName = MasterGenerator.GetSuitableProjectName(
                solutionName,
                GenerationTypes.PROJECT_TYPE_MAIN_VWG,
                GenerationTypes.SOLUTION_TYPE_DUALWINVWG);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName + ".VWG", projectName);
        }

        [Test]
        public void Test_GetSuitableProjectName_UI_ForUIVWG()
        {
            //---------------Set up test pack-------------------
            string solutionName = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string projectName = MasterGenerator.GetSuitableProjectName(
                solutionName,
                GenerationTypes.PROJECT_TYPE_UI_VWG,
                GenerationTypes.SOLUTION_TYPE_VWG);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName + ".UI", projectName);
        }

        [Test]
        public void Test_GetSuitableProjectName_UI_ForUIWin()
        {
            //---------------Set up test pack-------------------
            string solutionName = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string projectName = MasterGenerator.GetSuitableProjectName(
                solutionName,
                GenerationTypes.PROJECT_TYPE_UI_WIN,
                GenerationTypes.SOLUTION_TYPE_WIN);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName + ".UI", projectName);
        }

        [Test]
        public void Test_GetSuitableProjectName_UIVWG_ForDual()
        {
            //---------------Set up test pack-------------------
            string solutionName = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string projectName = MasterGenerator.GetSuitableProjectName(
                solutionName,
                GenerationTypes.PROJECT_TYPE_UI_VWG,
                GenerationTypes.SOLUTION_TYPE_DUALWINVWG);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName + ".UI.VWG", projectName);
        }

        [Test]
        public void Test_GetSuitableProjectName_UIWin_ForDual()
        {
            //---------------Set up test pack-------------------
            string solutionName = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string projectName = MasterGenerator.GetSuitableProjectName(
                solutionName,
                GenerationTypes.PROJECT_TYPE_UI_WIN,
                GenerationTypes.SOLUTION_TYPE_DUALWINVWG);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName + ".UI.Win", projectName);
        }

        [Test]
        public void Test_GetSuitableProjectName_Logic()
        {
            //---------------Set up test pack-------------------
            string solutionName = TestUtilsCodeGen.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string projectName = MasterGenerator.GetSuitableProjectName(
                solutionName,
                GenerationTypes.PROJECT_TYPE_LOGIC,
                TestUtilsCodeGen.GetRandomString());
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName + ".Logic", projectName);
        }

        [Test]
        public void Test_GetOrderedProjectTypeGenerations_EmptyCollection_ReturnsEmptyCollection()
        {
            //---------------Set up test pack-------------------
            BusinessObjectCollection<ProjectTypeGeneration> inputCol = new BusinessObjectCollection<ProjectTypeGeneration>();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, inputCol.Count);
            //---------------Execute Test ----------------------
            BusinessObjectCollection<ProjectTypeGeneration> outputCol = MasterGeneratorSpy.CallGetOrderedProjectTypeGenerations(inputCol);
            //---------------Test Result -----------------------
            Assert.IsNotNull(outputCol);
            Assert.AreEqual(0, outputCol.Count);
        }

        [Test]
        public void Test_GetOrderedProjectTypeGenerations_SingleItemCollection_ReturnsSame()
        {
            //---------------Set up test pack-------------------
            BusinessObjectCollection<ProjectTypeGeneration> inputCol = new BusinessObjectCollection<ProjectTypeGeneration>();
            inputCol.CreateBusinessObject();
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, inputCol.Count);
            //---------------Execute Test ----------------------
            BusinessObjectCollection<ProjectTypeGeneration> outputCol = MasterGeneratorSpy.CallGetOrderedProjectTypeGenerations(inputCol);
            //---------------Test Result -----------------------
            Assert.IsNotNull(outputCol);
            Assert.AreEqual(1, outputCol.Count);
        }

        [Test]
        public void Test_GetOrderedProjectTypeGenerations_TwoItemCollection_ReturnsBOFirst()
        {
            //---------------Set up test pack-------------------
            BusinessObjectCollection<ProjectTypeGeneration> inputCol = new BusinessObjectCollection<ProjectTypeGeneration>();
            ProjectTypeGeneration ptGenUIWin = TestUtilsProjectTypeGeneration.CreateUnsavedValidProjectTypeGeneration();
            ProjectTypeGeneration ptGenBO = TestUtilsProjectTypeGeneration.CreateUnsavedValidProjectTypeGeneration();
            ptGenUIWin.ProjectType.Name = "UI.Win";
            ptGenBO.ProjectType.Name = "BO";
            inputCol.Add(ptGenUIWin);
            inputCol.Add(ptGenBO);
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, inputCol.Count);
            Assert.AreEqual(ptGenUIWin, inputCol[0]);
            Assert.AreEqual(ptGenBO, inputCol[1]);
            //---------------Execute Test ----------------------
            BusinessObjectCollection<ProjectTypeGeneration> outputCol = MasterGeneratorSpy.CallGetOrderedProjectTypeGenerations(inputCol);
            //---------------Test Result -----------------------
            Assert.IsNotNull(outputCol);
            Assert.AreEqual(2, outputCol.Count);
            Assert.AreEqual(ptGenBO, outputCol[0]);
            Assert.AreEqual(ptGenUIWin, outputCol[1]);
        }

        [Test]
        public void Test_GetOrderedProjectTypeGenerations_FullHierarchy()
        {
            //---------------Set up test pack-------------------
            string[] typeGenerations = new[]
            {
               GenerationTypes.PROJECT_TYPE_TEST_UI,
               GenerationTypes.PROJECT_TYPE_TEST_LOGIC,
               GenerationTypes.PROJECT_TYPE_TEST_BO,
               GenerationTypes.PROJECT_TYPE_TEST_BASE,
               GenerationTypes.PROJECT_TYPE_MAIN_WIN,
               GenerationTypes.PROJECT_TYPE_MAIN_VWG,
               GenerationTypes.PROJECT_TYPE_UI_WIN,
               GenerationTypes.PROJECT_TYPE_UI_VWG,
               GenerationTypes.PROJECT_TYPE_UI_BASE,
               GenerationTypes.PROJECT_TYPE_LOGIC,
               GenerationTypes.PROJECT_TYPE_BO
            };
            BusinessObjectCollection<ProjectTypeGeneration> inputCol = new BusinessObjectCollection<ProjectTypeGeneration>();
            foreach (string typeGen in typeGenerations)
            {
                ProjectTypeGeneration ptGen = TestUtilsProjectTypeGeneration.CreateUnsavedValidProjectTypeGeneration();
                ptGen.ProjectType.Name = typeGen;
                inputCol.Add(ptGen);
            }
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            BusinessObjectCollection<ProjectTypeGeneration> outputCol = MasterGeneratorSpy.CallGetOrderedProjectTypeGenerations(inputCol);
            //---------------Test Result -----------------------
            BusinessObjectCollection<ProjectTypeGeneration> expectedCol = new BusinessObjectCollection<ProjectTypeGeneration>();
            for (int count = outputCol.Count - 1; count >= 0; count--)
            {
                expectedCol.Add(inputCol[count]);
            }
            Assert.AreEqual(expectedCol, outputCol);
        }

        [Test]
        public void Test_GetOrderedProjectTypeGenerations_UnknownTypes()
        {
            //---------------Set up test pack-------------------
            BusinessObjectCollection<ProjectTypeGeneration> inputCol = new BusinessObjectCollection<ProjectTypeGeneration>();
            ProjectTypeGeneration ptGenUnknown = TestUtilsProjectTypeGeneration.CreateUnsavedValidProjectTypeGeneration();
            ProjectTypeGeneration ptGenBO = TestUtilsProjectTypeGeneration.CreateUnsavedValidProjectTypeGeneration();
            ptGenUnknown.ProjectType.Name = TestUtilsCodeGen.GetRandomString();
            ptGenBO.ProjectType.Name = "BO";
            inputCol.Add(ptGenUnknown);
            inputCol.Add(ptGenBO);
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, inputCol.Count);
            Assert.AreEqual(ptGenUnknown, inputCol[0]);
            Assert.AreEqual(ptGenBO, inputCol[1]);
            //---------------Execute Test ----------------------
            BusinessObjectCollection<ProjectTypeGeneration> outputCol = MasterGeneratorSpy.CallGetOrderedProjectTypeGenerations(inputCol);
            //---------------Test Result -----------------------
            Assert.IsNotNull(outputCol);
            Assert.AreEqual(2, outputCol.Count);
            Assert.AreEqual(ptGenBO, outputCol[0]);
            Assert.AreEqual(ptGenUnknown, outputCol[1]);
        }

        private static DMSolution CreateDMSolution()
        {
            DMSolution dmSolution = new DMSolution();
            dmSolution.GenerationSettings = new GenerationSettings();
            dmSolution.GenerationSettings.SolutionDirectory = Path.Combine(Directory.GetCurrentDirectory(),
                                                                           TestUtilsCodeGen.GetRandomString());
            dmSolution.GenerationSettings.SolutionType = CreateSolutionType();
            return dmSolution;
        }

        private static DMSolution CreateValidDMSolution()
        {
            DMSolution dmSolution = TestUtilsDMSolution.CreateSavedDMSolution();
            UpdateSolutionWithValidDetailsForGeneration(dmSolution);
            return dmSolution;
        }

        private static void UpdateSolutionWithValidDetailsForGeneration(DMSolution dmSolution)
        {
            dmSolution.SolutionDirectory = Path.Combine(Directory.GetCurrentDirectory(), "FStartFolder");
            dmSolution.GenerationSettings = new GenerationSettings();
            dmSolution.GenerationSettings.SolutionName = "A" + TestUtilsCodeGen.GetRandomString();
            dmSolution.GenerationSettings.SolutionDirectory = TestUtilsCodeGen.GetRandomString();
            dmSolution.GenerationSettings.HabaneroDllPath = TestUtilsCodeGen.GetRandomString();
            SolutionType solutionType = new SolutionType();
            solutionType.Name = TestUtilsCodeGen.GetRandomString();
            dmSolution.GenerationSettings.SolutionType = solutionType;
            dmSolution.GenerationSettings.CodeTemplateLibraryName = TestUtilsShared.GetRandomEnum<CodeTemplateEnum>();
        }

        private static ProjectType CreateProjectType(string typeName)
        {
            ProjectType projectType = new ProjectType();
            projectType.Name = typeName;
            projectType.Save();
            return projectType;
        }

        private static SolutionType CreateSolutionType()
        {
            return CreateSolutionType(TestUtilsShared.GetRandomString());
        }

        private static SolutionType CreateSolutionType(string solutionTypeName)
        {
            SolutionType solutionType = new SolutionType();
            solutionType.Name = solutionTypeName;
            solutionType.Save();
            return solutionType;
        }
    }

    internal class ProjectGeneratorStub : ProjectGenerator
    {
        public bool HasGenerated { get; private set; }

        public ProjectGeneratorStub()
        {
            HasGenerated = false;
        }

        public override Result Generate()
        {
            HasGenerated = true;
            return new Result(true);
        }
    }

    internal class SolutionGeneratorStub : ISolutionGenerator
    {
        public bool HasGenerated { get; private set; }
        public CodeTemplateEnum CodeTemplateLibrary { get; private set; }

        public SolutionGeneratorStub()
        {
            HasGenerated = false;
        }

        public Result Generate(CodeTemplateEnum codeTemplate)
        {
            CodeTemplateLibrary = codeTemplate;
            HasGenerated = true;
            return new Result(true);
        }

        public string SolutionName
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public string SolutionDirectory
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public List<string> ProjectFileNames
        {
            get { throw new NotImplementedException(); }
        }

        public List<IProjectGenerator> ProjectGenerators
        {
            get { throw new System.NotImplementedException(); }
        }

        public string HabaneroReferencePath
        {
            get { throw new System.NotImplementedException(); }
            set { throw new System.NotImplementedException(); }
        }

        public IModelSolution ModelSolution
        {
            get { throw new System.NotImplementedException(); }
            set { throw new System.NotImplementedException(); }
        }

        public string SolutionTypeName
        {
            get { throw new System.NotImplementedException(); }
            set { throw new System.NotImplementedException(); }
        }

        public IList<IModelClass> ModelClasses
        {
            get { return new List<IModelClass>();}
            set { throw new System.NotImplementedException(); }
        }

        public string ClassDefsString
        {
            get { throw new System.NotImplementedException(); }
            set { throw new System.NotImplementedException(); }
        }

        public CodeTemplateEnum CodeTemplate
        {
            get { throw new System.NotImplementedException(); }
            set { throw new System.NotImplementedException(); }
        }
    }

    class MasterGeneratorSpy : MasterGenerator
    {
        public static BusinessObjectCollection<ProjectTypeGeneration> CallGetOrderedProjectTypeGenerations(BusinessObjectCollection<ProjectTypeGeneration> inputCol)
        {
            return GetOrderedProjectTypeGenerations(inputCol);
        }
    }
}
